package com.lingjtx.common.thread.commom;

import com.lingjtx.common.core.ResponseCode;
import com.lingjtx.common.core.ResponseResult;
import com.lingjtx.common.core.constant.Const;
import com.lingjtx.common.core.constant.ServiceName;
import com.lingjtx.common.core.token.AuthToken;
import com.lingjtx.common.core.util.CommonUtil;
import com.lingjtx.common.core.util.StringUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

@Component
public class ApiKeyFilter implements WebFilter, ErrorWebExceptionHandler {

    @Value("${api.auth-ignore:/image}")
    private String ignoreAuth;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getPath().value();
        // 白名单路径跳过验证
        if (isIgnoredPath(path)) {
            return chain.filter(exchange);
        }
        String apikey = request.getHeaders().getFirst(Const.AuthTokenMap.AUTHORIZATION);
        String sign = CommonUtil.getBasicAuth(ServiceName.PROJECT, Const.MD5_SALT);

        if (StringUtil.isEmpty(apikey)) {
            return retResponse(exchange, ResponseResult.createByError(ResponseCode.NOT_LOGIN.getCode(), "apikey 或 token 不能为空！"));
        }
        if (!sign.equals(apikey) && AuthToken.isExpTime(apikey)) {
            return retResponse(exchange, ResponseResult.createByError(ResponseCode.UNAUTHORIZED.getCode(), "API KEY 验证不匹配！"));
        }
        return chain.filter(exchange);
    }

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        return retResponse(exchange, ResponseResult.createByError(ex.getMessage()));
    }

    // 白名单匹配方法
    private boolean isIgnoredPath(String path) {
        String[] arr = ignoreAuth.split(",");
        for (String ignore : arr) {
            if (path.startsWith(ignore)) {
                return true;
            }
        }
        return false;
    }

    private Mono<Void> retResponse(ServerWebExchange exchange, ResponseResult<String> error) {
        ServerHttpResponse response = exchange.getResponse();
        DataBuffer buffer = response.bufferFactory().wrap(error.toString().getBytes(StandardCharsets.UTF_8));
        return response.writeWith(Mono.just(buffer));
    }
}
